/************************************************************************************
**  
* @copyright (c) 2015-, Technology Co., LTD. All Right Reserved.
*
*************************************************************************************/
/**
* @file     duye_cap_tcp_service.cpp
* @version     
* @brief      
* @author   
* @date     2013-01-09
* @note 
*
*  1. 2018-01-09 created this file
* 
*/
#include <duye_system.h>
#include <duye_logger.h>
#include <duye_cap_tcp_service.h>

static const int8* DUYE_LOG_PREFIX = "duye.cap.tcp.service";

namespace duye {

bool TcpServiceFilterWorker::filterPkt(const PacketReference& pktRef, const FilterRule& rule) {
	if (pktRef->getTfLayerProto() == rule.whiteRuleList().begin()->protocol()) {
		return true;
	}
	return false;
}

TcpService::TcpService() : CapDataService("TcpService") {
	FilterRule serviceRule;

	// tcp filter rule
	RuleItem ruleItem;
	ruleItem.setProtocol(PROTO_TCP);

	// setting rules
	serviceRule.addWhiteRule(ruleItem);
	serviceRule.setFilterWorker(&m_filterWorker);
	
	NetLayerService::instance().addListener(this, &serviceRule);
}

TcpService::~TcpService() {
	for (TcpListenerMap::iterator iter = m_listenerMap.begin(); iter != m_listenerMap.end(); ++iter) {
		delete iter->second;
	}

	m_listenerMap.clear();
}

bool TcpService::start() {
	startTask();
	return true;
}

bool TcpService::stop() {
	return true;
}

bool TcpService::run() {
	DUYE_INFO("TcpService Start");

	for (;;) {
		DUYE_INFO("TcpService Working");
		System::sleep(10);
	}

	DUYE_INFO("TcpService Exit");

	return true;
}

bool TcpService::addListener(DataServiceListener* listener, const FilterRule* filterRule) {
	TcpListener* tcpListener = dynamic_cast<TcpListener*>(listener);
	if (tcpListener == NULL) {
		return false;
	}
	
	FilterRule* copyFilterRule = NULL;
	if (filterRule == NULL) {
		m_listenerMap.insert(std::make_pair(tcpListener, copyFilterRule));
	} else {
		copyFilterRule = new FilterRule(*filterRule);
		m_listenerMap.insert(std::make_pair(tcpListener, copyFilterRule));
	}

	return true;
}

bool TcpService::delListener(DataServiceListener* listener) {
	m_listenerMap.erase(dynamic_cast<TcpListener*>(listener));
	return true;
}

int32 TcpService::onNetLayerPacket(const PacketReference& pktRef) {
	if (pktRef.isNull()) {
		DUYE_ERROR("pktRef.isNull()");
		return -1;
	}

	if (pktRef->getTfLayerProto() != PROTO_TCP)	{
		return -1;
	}

	DUYE_DEBUG(" Protocol type(%d) is %s.\n", 
		pktRef->getTfLayerProto(), 
		Protocols::instance().getName(pktRef->getTfLayerProto()).c_str());

	const TcpSession* tcpSession = m_tcpSessionManager.pushPacket(pktRef);
	for (TcpListenerMap::iterator iter = m_listenerMap.begin(); iter != m_listenerMap.end(); ++iter) {
		if (FilterEngine::instance().filterPkt(pktRef, iter->second)) {
			iter->first->onTcpPacket(pktRef);
			if (tcpSession != NULL)
			{
				iter->first->onTcpSession(pktRef, *tcpSession);
			}
		}
	}

	m_tcpSessionManager.checkLifecycle(tcpSession);

	return 0;
}

}
